package ru.susu.algebra.centralunits;

import java.io.PrintStream;
import java.math.BigInteger;
import java.util.Date;
import java.util.Iterator;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;

import ru.susu.algebra.centralunits.alternating.AlternatingGroupCentralUnitsSearcher;
import ru.susu.algebra.centralunits.alternating.initializers.LocalUnitsInitializer;
import ru.susu.algebra.centralunits.alternating.initializers.QuadraticFieldsInitializer;
import ru.susu.algebra.centralunits.alternating.initializers.SpecialRowsInitializer;
import ru.susu.algebra.centralunits.alternating.tex.HeadAnTexGenerator;
import ru.susu.algebra.centralunits.alternating.tex.local.LocalUnitTheorem;
import ru.susu.algebra.field.quadratic.QuadraticFieldGeneralForm;
import ru.susu.algebra.io.FileUtilities;
import ru.susu.algebra.iterators.SimpleForIntegerIterator;
import ru.susu.algebra.jtex.ITexDocument;
import ru.susu.algebra.jtex.ITexElement;
import ru.susu.algebra.jtex.StringTexElement;
import ru.susu.algebra.jtex.TexDocument;
import ru.susu.algebra.jtex.formula.GreekSymbols;
import ru.susu.algebra.jtex.utils.TexUtils;
import ru.susu.algebra.methods.IMathMethodPS;
import ru.susu.algebra.partition.Partition;
import ru.susu.algebra.properties.IOptionsSource;
import ru.susu.algebra.properties.IPropertySource;
import ru.susu.algebra.properties.MapPropertySource;

/**
 * @author akargapolov
 * @since: 14.11.2011
 */
public class ListCentralUnitsExecutor
{
	public static void main(String[] args) throws Exception
	{
		BasicConfigurator.configure();

		BigInteger.valueOf(5).divide(BigInteger.valueOf(2));
		IPropertySource ps = new AlternatingUnitsOptionsSource().getProperties();
		new ListCentralUnitSearcher().run(ps);
	}

	private static class AlternatingUnitsOptionsSource implements IOptionsSource
	{
		public static final int START_NUMBER = 5;
		public static final int END_NUMBER = 30;

		@Override
		public IPropertySource getProperties()
		{
			IPropertySource ps = new MapPropertySource();
			ps.setValue(CentralUnitsOptions.NUMBERS_ITERATOR, new SimpleForIntegerIterator(START_NUMBER, END_NUMBER, 1));
			ps.setValue(CentralUnitsOptions.UNITS_SEARCHER_CLASS, AlternatingGroupCentralUnitsSearcher.class.getName());
			return ps;
		}
	}

	private static class ListCentralUnitSearcher<R> implements IMathMethodPS<R>
	{
		private static final String FILENAME_PREFIX = "results/list_units/";
		private static final String FILENAME = "results/list_units/list_units.tex";
		@Override
		public R run(IPropertySource ps) throws Exception
		{
			Iterator<Integer> iterator = (Iterator<Integer>)ps.getValue(CentralUnitsOptions.NUMBERS_ITERATOR);
			ITexDocument document = new TexDocument();

			//стили и настройки
			document.setHead(new HeadAnTexGenerator().run(ps)).newLine();

			document.addElement(StringTexElement.text("\\begin{center} \n \\begin{tabular}{|r|r|r|} \n  " +
					"\\multicolumn{3}{c}{\\bf{Результаты вычислений}} \\\\ \n" +
					"\\hline " +
					"$n$ & $\\chi$  & $\\lambda$ \\\\ \n " +
					"\\hline"));

			while (iterator.hasNext())
			{
				IPropertySource sps = new MapPropertySource();
				Integer number = iterator.next();
				sps.setValue(CentralUnitsOptions.NUMBER, number);
				sps.setValue("document", document);
				new ListAlternatingGroupCentralUnitsSearcher().run(sps);
			}
			document.addElement(StringTexElement.text("  \\hline \n \\end{tabular} \n \\end{center}"));

			FileUtilities.makeDirectory(FILENAME_PREFIX);
			PrintStream stream = FileUtilities.createBufferedFilePrintStream(FILENAME);
			stream.write(document.generateContent().getBytes("cp1251"));
			//stream.write(document.generateContent().getBytes("utf8"));
			stream.close();
			return null;
		}
	}

	public static class ListAlternatingGroupCentralUnitsSearcher implements IMathMethodPS<ITexDocument>
	{
		private static final Logger _log = Logger.getLogger("searcher");

		@Override
		public synchronized ITexDocument run(IPropertySource ps) throws Exception
		{
			_log.info("Start for " + CentralUnitsOptions.getNumber(ps));
			Date start = new Date();
			ITexDocument document = (ITexDocument)ps.getValue("document");

			//локальный случай
			document.addElement(new LocalUnitTheorem()
			{
				@Override
				protected ITexElement getElement(Partition partition, IPropertySource ps) throws Exception
				{
					//n & \hi_rownumber & labmda & central_unit
					QuadraticFieldGeneralForm generateUnit = QuadraticFieldsInitializer.getGeneralUnit(ps, partition);
					BigInteger pow = LocalUnitsInitializer.getPow(ps, partition);


					String content = " $" + partition.getPresentedNumber() + "$ & $" +
						GreekSymbols.CHI + TexUtils.index(SpecialRowsInitializer.getRowNumber(ps, partition)) + "$ & $" +
//						AlternatingCharTableUtil.getSpecialCharacter(partition) + "$ & $" +
						TexUtils.inBrackets(TexUtils.toTexString(generateUnit)) + TexUtils.pow(pow) + "$ \\\\ \n";
					return StringTexElement.text(content);
					//return UnionTexElement.union().addSubElement(getTheorem(partition, ps)).addSubElement(StringTexElement.newLineDouble());
				}
			}
			.run(ps)).addElement(StringTexElement.newLineDouble());

			_log.info("End " + CentralUnitsOptions.getNumber(ps) + " - " + (new Date().getTime() - start.getTime()) + "ms");

			return document;
		}
	}
}
